# ==========================================================================#
#                          UI 类，继承Ui_MainWindow
# 功能：显示UI
#      定义按键信号
#      打开服务器
#      设置智能体起始位置
# ==========================================================================#
import json
import sys

from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QAbstractItemView, QMessageBox
from PyQt5 import QtWidgets, uic
from PyQt5.QtWidgets import QApplication, QWidget

import global_var
from thread_first import Thread

import numpy as np
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt

# class MyWindow(window_main.Ui_MainWindow):
#     def __init__(self, MainWindow):
#         super().setupUi(MainWindow)

class MyWindow(QWidget):
    robot_data = pyqtSignal(str)
    move_signal = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.ui = uic.loadUi("D:/PycharmProjects/001/src/BSD01/designer/window_main.ui")

        self.layout = QtWidgets.QVBoxLayout(self.ui.groupBox_1)

        self.figure = plt.figure(figsize=(10, 10), dpi=120)
        # self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)

        self.layout.addWidget(self.canvas)

        # 只有服务器启动后，起始位置设置按钮才有效
        self.ui.start_pushButton.setEnabled(False)

        # 声明信号
        self.signal_fun()

        # ================ 开启服务器子线程（创建socket套接字） ================#
        self.thread = Thread(self.ui,self.robot_data,self.move_signal)
        self.thread.start()

    # ================ 处理从子线程传回的客户端消息 ================#
    def robot_data_handle(self,client_data):
        if '{' in client_data:
            client_data = json.loads(client_data)
            ID = client_data.get("ID")
            current_x = client_data.get("current_x")
            current_y = client_data.get("current_y")
            print("ID:", ID, "  current_x:", current_x, "  current_y:", current_y)
            # 对应智能体的对象成员赋值
            global_var.get_one_Robot_list(ID - 1).current_x = current_x
            global_var.get_one_Robot_list(ID - 1).current_y = current_y

            # ================ 基站部署算法 ================#
            # *****
            # *****

            # 绘图
            self.figure.clf()  # 清除figure
            plt.xlabel("X")  # X轴
            plt.ylabel("Y")  # Y轴
            plt.grid()

            x_array = []
            y_array = []
            for i in range(global_var.get_client_num()):

                x_array.append(global_var.get_one_Robot_list(i).current_x)
                y_array.append(global_var.get_one_Robot_list(i).current_y)
                point_title = str(i+1) + ":(" + str(x_array[-1]) + "," + str(y_array[-1]) + ")"
                plt.text(x_array[i] - len(point_title)/20-1, y_array[i] + 0.1,point_title)
            plt.plot(x_array,y_array,'ro',markersize=6)
            plt.axis([-3,11,-3,11])   # 设置显示区域范围
            self.figure.canvas.draw()
        else:
            print(client_data)

    # ================ 信号 ================#
    def signal_fun(self):
        # 1.初始位置设置按键信号
        self.ui.start_pushButton.clicked.connect(self.start_pushButton_clicked)
        # 2.TCP服务器按键信号
        self.ui.server_pushButton.clicked.connect(self.server_pushButton_clicked)
        # 3.接收客户端消息
        self.robot_data.connect(self.robot_data_handle)
        # ====== 小车 ====== #
        # 4.上键（按键按压就有效果）
        self.ui.on_pushButton.pressed.connect(self.on_pushButton_pressed)
        self.ui.on_pushButton.released.connect(self.all_pushButton_released)
        # 5.下键
        self.ui.down_pushButton.pressed.connect(self.down_pushButton_pressed)
        self.ui.down_pushButton.released.connect(self.all_pushButton_released)
        # 6.左键
        self.ui.left_pushButton.pressed.connect(self.left_pushButton_pressed)
        self.ui.left_pushButton.released.connect(self.all_pushButton_released)
        # 7.右键
        self.ui.right_pushButton.pressed.connect(self.right_pushButton_pressed)
        self.ui.right_pushButton.released.connect(self.all_pushButton_released)

    # ================ 槽函数 ================#
    # 1.智能体初始位置设置按键
    def start_pushButton_clicked(self):
        if self.ui.start_pushButton.text() == '确定':
            res = QMessageBox.information(None, "", "确定起始位置已设置完成？", QMessageBox.Yes | QMessageBox.No)
            if res == QMessageBox.Yes:
                # ---- 1.遍历tableWidget的所有行，获取Robots的初始位置 ---- #
                xy_array = np.empty(shape=[0, 2])  # 保存xy坐标
                for i in range(self.ui.tableWidget.model().rowCount()):
                    # 没有被编辑前的空 && 被编辑后又删除后的空
                    if self.ui.tableWidget.item(i, 0) and self.ui.tableWidget.item(i, 0).text() and self.ui.tableWidget.item(i,1) and self.ui.tableWidget.item(i, 1).text():
                        xy_array = np.append(xy_array, [float(self.ui.tableWidget.item(i, 0).text()),float(self.ui.tableWidget.item(i, 1).text())])
                    else:
                        break
                xy_array = xy_array.reshape(int(xy_array.shape[0] / 2), 2)  # 修改数组形状，改成n行两列
                print('初始位置数组:\n', xy_array)

                # ---- 2.当tablewidget中的行数等于智能体个数且大于0时，才允许设置Robots的初始位置 ---- #
                if xy_array.shape[0] > 0 and xy_array.shape[0] == global_var.get_client_num():
                    for i in range(xy_array.shape[0]):
                        global_var.get_one_Robot_list(i).start_x = xy_array[i][0]
                        global_var.get_one_Robot_list(i).current_x = xy_array[i][0]

                        global_var.get_one_Robot_list(i).start_y = xy_array[i][1]
                        global_var.get_one_Robot_list(i).current_y = xy_array[i][1]
                    # 将初始位置发送给每个智能体(Json数据)
                    for i in range(global_var.get_client_num()):
                        data = {"header":"start","start_x": global_var.get_one_Robot_list(i).start_x, "start_y": global_var.get_one_Robot_list(i).start_y}
                        # global_var.set_Send_data("header", "start")
                        # global_var.set_Send_data("start_x", global_var.get_one_Robot_list(i).start_x)
                        # global_var.set_Send_data("start_y", global_var.get_one_Robot_list(i).start_y)
                        global_var.get_one_clientsockets(i).send(json.dumps(data).encode())
                        # 输出智能体初始位置
                        print(i + 1, ': start_x: ', global_var.get_one_Robot_list(i).start_x, '  start_y: ', global_var.get_one_Robot_list(i).start_y)

                    print('设置起始坐标成功')
                    # tableWidget不可编辑
                    self.ui.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
                    self.ui.start_pushButton.setText('取消')
                else:
                    QMessageBox.information(None, "", "位置数量与智能体个数不符", QMessageBox.Ok)
        else:
            if self.ui.start_pushButton.text() == '取消':
                res = QMessageBox.information(None, "", "确定重新设置起始位置吗？", QMessageBox.Yes | QMessageBox.No)
                if res == QMessageBox.Yes:
                    print('取消起始位置')
                    self.ui.start_pushButton.setText('确定')
                    # 双击可编辑(也可以CurrentChanged、SelectedClicked)
                    self.ui.tableWidget.setEditTriggers(QAbstractItemView.DoubleClicked)

    # 2.打开TCP服务器按键函数
    def server_pushButton_clicked(self):
        if self.ui.server_pushButton.text() == '打开':
            # res = QMessageBox.information(None, "", "确定开启服务器？", QMessageBox.Yes | QMessageBox.No)
            # if res == QMessageBox.Yes:
                ip = self.ui.comboBox.currentText()
                port = self.ui.lineEdit_2.text()
                listen_max = self.ui.lineEdit_3.text()
                self.thread.open_server.emit(json.dumps({"ip": ip, "port": port, "listen_max": listen_max}))
        else:
            # res = QMessageBox.information(None, "", "确定关闭服务器？", QMessageBox.Yes | QMessageBox.No)
            # if res == QMessageBox.Yes:
                self.thread.close_server.emit()
                self.ui.server_pushButton.setText('打开')
                # 编辑框可编辑
                self.ui.comboBox.setEditable(True)
                self.ui.lineEdit_2.setEnabled(True)
                self.ui.lineEdit_3.setEnabled(True)
                # 起始位置按钮失效
                self.ui.start_pushButton.setEnabled(False)

    # 3.前进
    def on_pushButton_pressed(self):
        self.move_signal.emit(json.dumps({"move": "up"}))
    # 4.后退
    def down_pushButton_pressed(self):
        self.move_signal.emit(json.dumps({"move": "down"}))
    # 5.左移
    def left_pushButton_pressed(self):
        self.move_signal.emit(json.dumps({"move": "left"}))
    # 6.右移
    def right_pushButton_pressed(self):
        self.move_signal.emit(json.dumps({"move": "right"}))
    # 7.松键
    def all_pushButton_released(self):
        self.move_signal.emit(json.dumps({"move": "released"}))

# 192.168.31.145
if __name__ == '__main__':
    app = QApplication(sys.argv)

    # 初始化全局变量
    global_var.init()

    # 创建UI、主线程
    # window = QMainWindow()
    # myui = MyWindow(window)
    # window.show()

    myui = MyWindow()
    myui.ui.show()

    app.exec()

